package ad_exercise_3.model;

import java.util.Arrays;
import java.util.List;
import java.util.Random;

import ad_exercise_3.controller.Game;
import ad_exercise_3.model.Card.CardColour;

/**
 * Represents an abstract player.
 * 
 * @author Karen Berntsen (s0815799)
 * @author Erik Stens (s0615374)
 */
public abstract class Player {
	private static CustomList<String>	nameList	= getNameList();
	private static final Random			random		= new Random();
	
	private String						name;
	protected CustomList<Card>			hand;
	protected final Game				game;
	
	public Player(CustomList<Card> initialHand, Game game) {
		this.game = game;
		if (nameList.size() > 0) {
			name = nameList.remove(random.nextInt(nameList.size()));
		} else {
			name = "Player_" + (game.getNumPlayers() + 1);
		}
		hand = initialHand;
	}
	
	public String getName() {
		return name;
	}
	
	public void takeCards(int numCards) {
		hand.addAll(game.takeCards(numCards));
	}
	
	public Player(String name, CustomList<Card> initialHand, Game game) {
		this.game = game;
		this.name = name;
		hand = initialHand;
	}
	
	public Card playCard() {
		return null;
	}
	
	public void toonHand() {
		for (int i = 0; i < hand.size(); i++) {
			System.out.println(i + ". \t" + hand.get(i));
		}
	}
	
	@Override
	public String toString() {
		return "NAME: " + name + ", HAND: " + hand.toString();
	}
	
	private static CustomList<String> getNameList() {
		List<String> nameList = Arrays.asList("Karen", "Erik", "Sjaak", "Pieter", "Ko", "Pol", "Marc");
		CustomList<String> nameCustomList = new CustomList<String>();
		nameCustomList.addAll(nameList);
		return nameCustomList;
	}
	
	/**
	 * This method makes sure the player either plays a card or takes a card from the stack (optionally playing the taken card)
	 * 
	 * @return the card to be played that the player chose from his hand. Null if the player couldn't/wouldn't play a card.
	 */
	public Card doTurn() {
		Card card = askCard();
		if (card != null) {
			return card;
		} else {
			card = game.takeCards(1).get(0);
			System.out.println("Player " + name + " had to take a card from the stack");
			if (keepCard(card) || !game.cardFits(card)) {
				System.out.println("Player " + name + " couldn't/wouldn't play the card");
				hand.add(card);
				return null;
			} else {
				return card;
			}
		}
	}
	
	public int getNumCards() {
		return hand.size();
	}
	
	/**
	 * 
	 * @param card
	 *            the card the player took from the stack
	 * 
	 * @return true of the player wants to keep the taken card, false if he wants to play it
	 */
	protected abstract boolean keepCard(Card card);
	
	/**
	 * Asks a player which card he wants to play, or if he doesn't want to play a card at all
	 * 
	 * @return the chosen card, null if no card was chosen
	 */
	protected abstract Card askCard();
	
	/**
	 * In case of a choice card, asks the player what colour this choice card should become
	 * 
	 * @return the {@link CardColour}
	 */
	public abstract CardColour askColour();
	
	/**
	 * @return description of the type of player
	 */
	public abstract String getType();
}
